<?php
/**
 * 框架 - 消息调度器类
 * 
 * @version $Id: Dispatcher.php 411 2012-12-31 08:03:18Z linsir123 $
 * @package Core
 */
class Dispatcher
{
	/**
	 * @var 控制器目录
	 */
	public $controllerDir;
	
	/**
	 * @var 控制器类名称
	 */
	public $controllerName;
	
	/**
	 * @var 控制器类
	 */
	public $controllerClass;
	
	/**
	 * 运行指定的控制器方式
	 * 
	 * @param string $controllerName 控制器名
	 * @param string $actionName 方法名
	 * @param bool $linkMethod 是否执行(前/后置)方法
	 */
	public function gotoCtrl($controllerName, $actionName = null, $linkMethod = true)
	{
		$this->controllerName = $controllerName;
		
		///
		$this->_dispatching($actionName, $linkMethod);
	}
	
	/**
	 * 直接抛出系统异常,由系统进行系统自定义控制器的调度
	 * 
	 * @param string $message 异常描述
	 */
	public function goto404($message)
	{
		throw new Exception("[Dispatcher] ". $message, 404);
		
		///
		lpSystem::h404();
		App::end();
	}
	
	
	/// 以下为私有方法 ///
	
	
	/**
	 * 分派消息
	 */
	private function _dispatching($actionName, $linkMethod = true)
	{
		$this->_checkCtrl();
		
		///
		$controller = App::singleton($this->controllerClass);
		$controller->runAction($this->controllerName, $actionName, $linkMethod);
	}
	
	/**
	 * 检测文件和类存在情况
	 * // 1、检测控制器名称
	 * // 2、初始化控制器所在目录
	 * // 3、其它检测
	 */
	private function _checkCtrl()
	{
		/// 1
		if (empty($this->controllerName)) 
			$this->controllerName = App::O('main.controllerDefault');
			
		$this->controllerName = ucfirst($this->controllerName);
		
		/// 2
		$this->_initCtrlDir();
		
		/// 3.1
		$this->controllerClass = 'controller'. $this->controllerName;
		if (class_exists($this->controllerClass, false)) 
			return ;
			
		/// 3.2
		$file = $this->controllerName .'.php';
		App::import($file, $this->controllerDir, false) or 
			$this->goto404("控制器文件({$file})不存在。");
			
		/// 3.3
		class_exists($this->controllerClass, false) or 
			$this->goto404("控制器类({$this->controllerClass})不存在。");
	}
	
	/**
	 * 初始化控制器目录
	 * // 1、解析配置
	 * // 2、构造相对路径别名
	 * // 3、解析控制器列表类别
	 */
	private function _initCtrlDir()
	{
		/// 1
		if (empty(App::$__subApp)) {
			$conf = App::O('main.appDefault');
			$alias = $conf['alias'];
			$listCtrl = $conf['list'];
		} else {
			$conf = App::O('main.appSubs');
			$alias = App::$__subApp;
			$listCtrl = $conf[$alias];
		}
		
		/// 2
		$this->controllerDir = APP_DIR .'Controller'. DS 
			. (empty($alias)?'':(ucfirst($alias) . DS));
			
		/// 3
		if (is_array($listCtrl)) {
			foreach ($listCtrl as $k => $v) {
				$list = glob($this->controllerDir . ucfirst($k) ."/*.php");
				if (empty($list) || ! is_array($list)) 
					continue;
					
				///
				foreach ($list as $file) {
					$name = basename($file, ".php");
					if (strcmp($name, $this->controllerName)===0) {
						$this->controllerDir .= ucfirst($k) . DS;
						break;
					}
				}
			}
		}
	}
}
